#ifndef _dso_plugin_h
#define _dso_plugin_h

#include <stdio.h>
#include <nds.h>
#include "dso_const.h"

#ifdef __cplusplus
extern "C" {
#endif

// a lot of this is very similar to the moonshell plugin format

typedef struct {  
	void (*pluginSetVBlank)(u32 uID, void (*vBlank)(void));
	void (*pluginClearVBlank)(u32 uID);
	void (*pluginSetDraw)(u32 uID, void (*draw)(uint16 *fb, uint16 *bg));
	void (*pluginClearDraw)(u32 uID);
	void (*pluginSetIRQ)(IRQ_MASK which, void (*func)());
	void (*pluginClearIRQ)(IRQ_MASK which);
	void (*resetScreens)(void);

	void (*debugPrint)(char *str);
	void (*debugPrintHalt)(char *str);

	void *(*calloc)(size_t nmemb, size_t size);
	void *(*malloc)(size_t size);
	void (*free)(void *ptr);
	void *(*realloc)(void *ptr, size_t size);
	
	int (*sprintf)(char * buffer, const char * format, ...);
	int (*sscanf)(const char *source, const char *format, ...);
	
	int (*rand)(void);
	
	void *(*memchr)(const void *buf, int ch, size_t n);
	int (*memcmp)(const void *buf1, const void *buf2,size_t n);
	void *(*memcpy)(void *buf1, const void *buf2, size_t n);
	void *(*memmove)(void *buf1, const void *buf2, size_t n);
	void *(*memset)(void *buf, int ch, size_t n);
	
	int (*abs)(int j);
	long int (*labs)(long int j);
	long long int (*llabs)(long long int j);
	
	double (*atof)(const char *nptr);
	int (*atoi)(const char *nptr);
	long (*atol)(const char *nptr);
	long long (*atoll)(const char *nptr);
	
	char *(*strcat)(char *dest, const char *src);
	char *(*strchr)(const char *s, int c);
	int (*strcmp)(const char *s1, const char *s2);
	int (*strcoll)(const char *s1, const char *s2);
	char *(*strcpy)(char *dest, const char *src);
	size_t (*strcspn)(const char *s, const char *reject);
	char *(*strdup)(const char *s);
	size_t (*strlen)(const char *s);
	char *(*strncat)(char *dest, const char *src, size_t n);
	int (*strncmp)(const char *s1, const char *s2, size_t n);
	char *(*strncpy)(char *dest, const char *src, size_t n);
	char *(*strpbrk)(const char *s, const char *accept);
	char *(*strrchr)(const char *s, int c);
	char *(*strsep)(char **stringp, const char *delim);
	size_t (*strspn)(const char *s, const char *accept);
	char *(*strstr)(const char *haystack, const char *needle);
	char *(*strtok)(char *s, const char *delim);
	size_t (*strxfrm)(char *dest, const char *src, size_t n);
	
	FAT_FILE *(*DRAGON_fopen)(const char* path, const char* mode);
	bool (*DRAGON_fclose)(FAT_FILE* file);
	int (*DRAGON_fseek)(FAT_FILE* file, s32 offset, int origin);
	u32 (*DRAGON_ftell)(FAT_FILE* file);
	u32 (*DRAGON_fread)(void* buffer, u32 size, u32 count, FAT_FILE* file);
	u32 (*DRAGON_fwrite)(const void* buffer, u32 size, u32 count, FAT_FILE* file);
	uint16 (*DRAGON_fgetc)(FAT_FILE* file);
	void (*DRAGON_fputc)(uint16 c, FAT_FILE* file);
	char *(*DRAGON_fgets)(char *tgtBuffer, int num, FAT_FILE* file);
	int (*DRAGON_fputs)(const char *string, FAT_FILE* file);
	bool (*DRAGON_feof)(FAT_FILE* file);
	
	int (*DRAGON_FileExists)(const char* filename);
	int (*DRAGON_remove)(const char* path);
	int (*DRAGON_mkdir)(const char* path);
	bool (*DRAGON_chdir)(const char* path);
	bool (*DRAGON_rename)(const char *oldName, const char *newName);
	
	bool (*DRAGON_GetAlias)(char* alias);
	bool (*DRAGON_GetLongFilename)(char* filename);
	u32 (*DRAGON_GetFileSize)(void);
	u32 (*DRAGON_GetFileCluster)(void);
	u8 (*DRAGON_GetFileAttributes)(void);
	u8 (*DRAGON_SetFileAttributes)(const char* filename, u8 attributes, u8 mask);
	int (*DRAGON_FindFirstFile)(char* lfn);
	int (*DRAGON_FindNextFile)(char* lfn);
	u32 (*DRAGON_flength)(FAT_FILE* df);
	u32 (*DRAGON_DiscType)(void);	
	
	void (*scanKeys)(void);
	uint32 (*keysHeld)(void);
	uint32 (*keysDown)(void);
	uint32 (*keysDownRepeat)(void);
	void (*keysSetRepeat)(u8 setDelay, u8 setRepeat);
	uint32 (*keysUp)(void);
	touchPosition (*touchReadXY)(void);
	
	void (*swiWaitForVBlank)(void);
	
	void (*connectWifi)(void);
	void (*disconnectWifi)(void);
	bool (*isConnected)(void);
	int (*Wifi_AssocStatus)(void);
	u32 (*ipToLong)(char i1, char i2, char i3, char i4);
	int (*wifiConnect)(char *host, unsigned short port);
	int (*wifiConnectIP)(u32 ip, unsigned short port);	
	int (*sendHTTPRequest)(char *req);
	void (*setBlocking)(int sock);
	void (*setNonBlocking)(int sock);
	void (*sendData)(int sock, char *data, int len);
	int (*recvData)(int sock, char *data, int len);
	int (*close)(int socket);
	void (*Wifi_DisableWifi)();
	void (*Wifi_EnableWifi)();
	void (*Wifi_SetPromiscuousMode)(int enable);
	void (*Wifi_ScanMode)();
	void (*Wifi_SetChannel)(int channel);
	int (*Wifi_GetNumAP)();
	int (*Wifi_GetAPData)(int apnum, Wifi_AccessPoint * apdata);
	int (*Wifi_FindMatchingAP)(int numaps, Wifi_AccessPoint * apdata, Wifi_AccessPoint * match_dest);
	int (*Wifi_ConnectAP)(Wifi_AccessPoint * apdata, int wepmode, int wepkeyid, unsigned char * wepkey);
	int (*Wifi_DisconnectAP)();
	unsigned long (*Wifi_GetIP)();
	unsigned long (*Wifi_GetIPInfo)(unsigned long * pGateway,unsigned long * pSnmask,unsigned long * pDns1,unsigned long * pDns2);
	void (*Wifi_SetIP)(unsigned long IPaddr, unsigned long gateway, unsigned long subnetmask, unsigned long dns1, unsigned long dns2);
	int (*Wifi_GetData)(int datatype, int bufferlen, unsigned char * buffer);
	u32 (*Wifi_GetStats)(int statnum);
	int (*Wifi_RawTxFrame)(unsigned short datalen, unsigned short rate, unsigned short * data);
	void (*Wifi_RawSetPacketHandler)(WifiPacketHandler wphfunc);
	int (*Wifi_RxRawReadPacket)(long packetID, long readlength, unsigned short * data);
	struct hostent *(*gethostbyname)(const char * name);
	int (*socket)(int domain, int type, int protocol);
	int (*bind)(int socket, const struct sockaddr * addr, int addr_len);
	int (*connect)(int socket, const struct sockaddr * addr, int addr_len);
	int (*send)(int socket, const void * data, int sendlength, int flags);
	int (*recv)(int socket, void * data, int recvlength, int flags);
	int (*sendto)(int socket, const void * data, int sendlength, int flags, const struct sockaddr * addr, int addr_len);
	int (*recvfrom)(int socket, void * data, int recvlength, int flags, struct sockaddr * addr, int * addr_len);
	int (*listen)(int socket, int max_connections);
	int (*accept)(int socket, struct sockaddr * addr, int * addr_len);
	int (*shutdown)(int socket, int shutdown_type);
	int (*setsockopt)(int socket, int level, int option_name, const void * data, int data_len);
	int (*getsockopt)(int socket, int level, int option_name, void * data, int * data_len);
	int (*getpeername)(int socket, struct sockaddr *addr, int * addr_len);
	int (*getsockname)(int socket, struct sockaddr *addr, int * addr_len);
	unsigned short (*htons)(unsigned short num);
	unsigned long (*htonl)(unsigned long num);
	int (*select)(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout);
	
	void (*libfb_swapBuffers)();
	void (*fb_swapBuffers)();
	void (*bg_swapBuffers)();
	uint16 *(*libfb_getDrawSurface)(int whichScreen);
	void (*libfb_setBGColor)(int whichScreen, uint16 color);
	void (*libfb_setPixel)(int whichScreen, int x, int y, uint16 color);
	void (*libfb_dispSprite)(int whichScreen, int x, int y, uint16 *sprite, uint16 tc);
	void (*libfb_dispRect)(int whichScreen, int x, int y, int bx, int by, uint16 color);
	void (*libfb_dispBox)(int whichScreen, int x, int y, int bx, int by, uint16 color);

	void (*setCursorPos)(uint32 pos);
	void (*setCursorOVR)(void);
	void (*setCursorINS)(void);
	void (*setCursorProperties)(uint16 color, int top, int height, int left);
	uint32 (*getPositionAbove)(void);
	uint32 (*getPositionBelow)(void);
	void (*setCallBack)(int (*callback)(int,uint16,int,int,int));
	void (*clearCallBack)(void);
	void (*setTwoPasEnabled)(bool t);
	void (*showCursor)(void);
	void (*hideCursor)(void);

	void (*libfb_setClipping)(int whichScreen, bool enabled, int x, int y, int w, int h);
	void (*setWrapToBorder)(void);
	void (*setWrapNormal)(void);
	void (*setColor)(uint16 color);
	void (*libfb_setFont)(int whichFont);
	void (*setBold)(bool);
	void (*setItalics)(bool);
	void (*setUnderline)(bool);
	int (*libfb_getStringWidth)(char *toDisp, int whichFont);
	int (*libfb_getWrapPoints)(int x, int y, char *toDisp, int c_x, int c_y, int c_bx, int c_by, int **pts, int whichFont);
	void (*libfb_dispString)(int whichScreen, int x, int y, char *toDisp);
	void (*libfb_dispChar)(int whichScreen, int x, int y, char toDisp);
	
	bool (*loadSound)(char *fName);
	void (*startSoundStream)(u32 uID, int rate, int multiplicity, int sampleLength, void (*fillBufferFunction)(s16 *lBuf, s16 *rBuf));
	void (*pauseSound)(bool pause);
	void (*getSoundLoc)(u32 *loc, u32 *max);
	void (*setSoundLoc)(u32 loc);
	void (*closeSound)(void);	
	
	int (*getState)();
	int (*getSourceFmt)();
	int (*getCurrentStatus)();
	u8 (*getVolume)();
	void (*setVolume)(u8 volume);
	
	// specific to DSO
	void (*separateExtension)(char *str, char *ext);
	void (*pluginAbbreviateString)(char *str, int maxLen, int whichFont);
	int (*pluginCenterOnPt)(int pt, char *str, int whichFont);
	void (*launchNDS)(char *file);
	void (*launchNDSAlt)(char *file);
	int (*pluginGetCurrentScreen)();
	void (*checkSleepState)();
	void (*writeDebug)(const char *s, ...);
	void (*sendPSGCommand)(int channel, u32 cr, u32 timer);
	
	// specific to controls
	void (*drawHome)();
	void (*drawTimeDate)();
	void (*drawButtonTextsEX)(char lBut, char *lText, char rBut, char *rText);
	void (*displayScrollHandle)(bool t);
	void (*drawScrollBarEX)(int pos, int max, bool isHeld, int x, int y, int width, int height);
	void (*drawListBox)(int tx, int ty, int bx, int by, int curEntry, int maxEntries, char *noString, void (*callback)(int, int, int));
	void (*drawLREX)(char *lText, bool lEnabled, char *rText, bool rEnabled);
	
	int (*getScroll)(int py, int max);	
	int (*getCursorFromTouch)(int u, int v);
} _plugin_struct;

extern const _plugin_struct *pluginLib;
extern u32 pluginUniqueID;

extern void DSO_LoadLibrary();
extern void DSO_FreeLibrary();
extern u32 DSO_QueryInterface(long,long);

#ifdef __cplusplus
}
#endif

#endif

